﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using USClientKernel.Template;
using Common.Utils;
using Common.Utils.Helper;
using Object = UnityEngine.Object;
using Game;
using Game.Logic.Manager;

namespace UIFramework
{
    public class GameUIManager : Singleton<GameUIManager>
    {
        private CSharpLuaTable m_uiConfigs;
        public CSharpLuaTable UiConfigs { get => m_uiConfigs; set => m_uiConfigs = value; }

        private Dictionary<UIContext, GameUIController> _dictOpenUIController;
        private Queue<UIContext> _queueOpenUIContext;
        private Stack<UIContext> _stackOpenUIContext;
        private GameObject m_canvasObj;
        private Canvas m_canvas;
        private Transform canvasTransform;
        private Image m_bgImage;

        public Transform CanvasTransform
        {
            get
            {
                if (null == canvasTransform)
                {
                    canvasTransform = m_canvasObj.transform;
                    Object.DontDestroyOnLoad(canvasTransform);
                }
                return canvasTransform;
            }
        }

        protected override void Init()
        {
            _dictOpenUIController = new Dictionary<UIContext, GameUIController>();
            _queueOpenUIContext = new Queue<UIContext>();
            _stackOpenUIContext = new Stack<UIContext>();
            InitUICanvas();
            m_uiConfigs = GameConfigManager.Instance.LoadConfig(GameDefine.GAME_CONFIG_UI);
        }

        private void InitUICanvas()
        {
            ResManager.Instance.LoadInstantiate<GameObject>(UIPathDefine.UI_CANVAS);
            m_canvasObj = GameObject.FindGameObjectWithTag(UITagDefine.TAG_UI_CANVAS);
            m_canvas = m_canvasObj.GetComponent<Canvas>();
            m_bgImage = UnityHelper.GetTheChildComponent<Image>(m_canvasObj, "UIBGImage");
        }


        public T GetUIController<T>(UIContext _context) where T : GameUIController
        {
            GameUIController retUIController = null;
            if (!_dictOpenUIController.TryGetValue(_context, out retUIController))
            {

            }
            return (T)retUIController;
        }


        public UIContext GetUIContext(ENUM_UITYPE _uiType, params object[] _uiParams)
        {
            UIContext uiContext = new UIContext(_uiType, _uiParams);

            //if (!UIPathDefine.ENUM_UITYPE_PATH.TryGetValue(_uiType, out string uiPath))
            uiContext.Path = GetUIConfigPath(_uiType);
            if (null == uiContext.Path)
                throw new Exception("Open Invaild UIPrefab path！ENUM_UITYPE:" + _uiType);


            //if (!UIPathDefine.ENUM_UIMODEL_PATH.TryGetValue(_uiType, out List<string> uiModelConfig))
            uiContext.Model = GetUIConfigModel(_uiType);
            if (null == uiContext.Model)
                throw new Exception("Open Invaild UIModel path！ENUM_UITYPE:" + _uiType);


            // if (!UIPathDefine.ENUM_UIVIEW_PATH.TryGetValue(_uiType, out List<string> uiViewConfig))
            uiContext.View = GetUIConfigView(_uiType);
            if (null == uiContext.View)
                throw new Exception("Open Invaild UIView path！ENUM_UITYPE:" + _uiType);

            uiContext.Module = GetUIConfigModule(_uiType);
            uiContext.Controller = GetUIConfigController(_uiType);

            return uiContext;
        }


        public CSharpLuaTable GetUIConfig(ENUM_UITYPE _uiType)
        {
            string t = _uiType.ToString();
            return UiConfigs[((int)_uiType).ToString()];
        }


        public string GetUIConfig(ENUM_UITYPE _uiType, string field)
        {
            CSharpLuaTable config = GetUIConfig(_uiType);
            if (null == config)
                return null;
            else
                return config.GetField(field);
        }

        public string GetUIConfigModel(ENUM_UITYPE _uiType)
        {
            return GetUIConfig(_uiType, "model");
        }

        public string GetUIConfigView(ENUM_UITYPE _uiType)
        {
            return GetUIConfig(_uiType, "view");
        }

        public string GetUIConfigModule(ENUM_UITYPE _uiType)
        {
            return GetUIConfig(_uiType, "module");
        }

        public string GetUIConfigPath(ENUM_UITYPE _uiType)
        {
            return GetUIConfig(_uiType, "path");
        }

        public string GetUIConfigController(ENUM_UITYPE _uiType)
        {
            return GetUIConfig(_uiType, "controller");
        }

        public void OpenUI(ENUM_UITYPE[] _uiTypes)
        {
            OpenUI(_uiTypes, null);
        }

        public void OpenUI(ENUM_UITYPE _uiType, params object[] _uiParams)
        {
            ENUM_UITYPE[] _uiTypes = new ENUM_UITYPE[1];
            _uiTypes[0] = _uiType;
            object[][] _uiArrParams = new object[1][];
            _uiArrParams[0] = _uiParams;
            OpenUI(_uiTypes, _uiArrParams);
        }


        public void OpenUI(ENUM_UITYPE[] _uiTypes, params object[][] _uiArrParams)
        {
            GameUIController uiController = null;
            UIContext oldContext = null;

            if (_stackOpenUIContext.Count > 0)
            {
                oldContext = _stackOpenUIContext.Peek();
                if(!_dictOpenUIController.TryGetValue(oldContext, out uiController))
                    throw new Exception("Pause Invaild UIContext！ENUM_UITYPE:" + oldContext.Type);
                uiController.OnPause();
            }

            for (int i = 0; i < _uiTypes.Length; i++)
            {
                ENUM_UITYPE _uiType = _uiTypes[i];
                object[] _uiParams = _uiArrParams[i];
                UIContext newContext = GetUIContext(_uiType, _uiParams);
                _queueOpenUIContext.Enqueue(newContext);
            }

            if (_queueOpenUIContext.Count > 0)
                CoroutineController.Instance.StartCoroutine(AsyncLoadData());
        }


        private IEnumerator<int> AsyncLoadData()
        {
            UIContext _curContext;
            if (null != _queueOpenUIContext && _queueOpenUIContext.Count > 0)
                do
                {
                    _curContext = _queueOpenUIContext.Dequeue();
                    GameUIController uiController;
                    if (null != _curContext.Controller)
                    {
                        uiController = ReflectionHelper.CreateInstance<GameUIController>(
                            string.Concat(GameDefine.GAME_NAMESPACE_LOGIC, ".", _curContext.Module), _curContext.Controller, CanvasTransform, _curContext);
                    }
                    else
                    {
                        uiController = new GameUIController(CanvasTransform, _curContext);
                    }
                    uiController.LoadUI();
                    _dictOpenUIController.Add(_curContext, uiController);
                    _stackOpenUIContext.Push(_curContext);
                } while (_queueOpenUIContext.Count > 0);
            yield return 0;
        }


        public void CloseUI()
        {
            if (_stackOpenUIContext.Count <= 0) return;

            UIContext _curContext = _stackOpenUIContext.Pop();
            GameUIController _curUIController;

            if (!_dictOpenUIController.TryGetValue(_curContext, out _curUIController))
                throw new Exception("Close Invaild UI ENUM_UITYPE:" + _curContext.Type);

            _dictOpenUIController.Remove(_curContext);
            _curUIController.OnExit();

            if (_stackOpenUIContext.Count <= 0) return;

            _curContext = _stackOpenUIContext.Peek();

            if (!_dictOpenUIController.TryGetValue(_curContext, out _curUIController))
                throw new Exception("Resume Invaild UI ENUM_UITYPE:" + _curContext.Type);

            _curUIController.OnResume();
        }



        #region Background Image Interface
        public void SetBackgroundImageEnable(bool _enable)
        {
            m_bgImage.gameObject.SetActive(_enable);
            //m_bgImage.enabled = _enable;
        }

        public void SetBackgroundImage(Texture2D _texture)
        {
            Sprite s = Sprite.Create(_texture, new Rect(0, 0, _texture.width, _texture.height), new Vector2(0, 0));
            SetBackgroundImage(s);
        }

        public void SetBackgroundImage(Sprite _sprite)
        {
            m_bgImage.sprite = _sprite;
        }

        public void ClearBackGroundImage()
        {
            m_bgImage.sprite = null;
        }
        #endregion
    }
}


